package com.czkevin.biliwsclient;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.czkevin.biliwsclient.data.User;
import com.czkevin.biliwsclient.data.UserWithFace;
import com.czkevin.biliwsclient.gift.GiftInfo;
import com.czkevin.biliwsclient.gift.GuardInfo;
import com.czkevin.biliwsclient.lottery.data.LotteryInfoQueryResult;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

public class LiveInfoHelper {

    private static String LOTTERY_INFO = "https://api.live.bilibili.com/xlive/lottery-interface/v1/Anchor/Info?roomid=%d";

    private static String GIFT_INFO = "https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/giftConfig?platform=pc";

    private static String METAL_ANCHOR_INFO = "https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuMedalAnchorInfo?ruid=%d";

    public static JSONObject getRoomConnection(String room) {
        String strRoomConf;
        try {
            strRoomConf = HTTPHelper.doGet("https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?type=0&id=" + room);
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("FAILED TO ACQUIRE ROOM CONFIG! ");
            return null;
        }
        JSONObject room_info = JSON.parseObject(strRoomConf);
        if(room_info.getInteger("code") != 0) {
            System.out.println("Failed to acquire room info, response: \n" + room_info.getString("message"));
            return null;
        }
        return room_info.getJSONObject("data");
    }

    public static String[] getUriAndToken(String room) {
        JSONObject data = getRoomConnection(room);
        if(data == null) return null;
        if(data.containsKey("host_list")) {
            JSONArray hosts = data.getJSONArray("host_list");
            if(hosts.size() <= 0) return null;
            JSONObject host = hosts.getJSONObject(0);
            String protocol;
            int port;
            if(host.containsKey("wss_port")) {
                protocol = "wss";
                port = host.getIntValue("wss_port");
            } else if (host.containsKey("ws_port")) {
                protocol = "ws";
                port = host.getIntValue("ws_port");
            } else {
                return null;
            }
            return new String[] {
                String.format("%s://%s:%d/sub", protocol, host.getString("host"), port),
                data.getString("token")
            };
        } else {
            return null;
        }
    }

    public static String getToken(String room) {
        JSONObject data = getRoomConnection(room);
        if(data == null) return null;
        return data.getString("token");
    }

    public static GiftConfig getGiftConfig() throws Exception {
        return getGiftConfig(null);
    }

    public static GiftConfig getGiftConfig(String roomId) throws Exception {
        String result = HTTPHelper.doGet(GIFT_INFO + (roomId != null ? String.format("&room_id=%s", URLEncoder.encode(roomId, "UTF-8")) : ""));
        JSONObject obj = JSON.parseObject(result);
        if(obj.getIntValue("code") != 0) {
            throw new IllegalStateException("code " + obj.getIntValue("code"));
        }
        JSONObject data = obj.getJSONObject("data");

        Map<Integer, GiftInfo> gifts = new HashMap<>();
        {
            JSONArray array = data.getJSONArray("list");
            for(int i = 0; i < array.size(); i++) {
                JSONObject jsonGift = array.getJSONObject(i);
                GiftInfo gift = GiftInfo.decode(jsonGift);
                gifts.put(gift.id, gift);
            }
        }

        Map<Integer, GuardInfo> guards = new HashMap<>();
        {
            JSONArray array = data.getJSONArray("guard_resources");
            for(int i = 0; i < array.size(); i++) {
                JSONObject jsonGift = array.getJSONObject(i);
                GuardInfo gift = GuardInfo.decode(jsonGift);
                guards.put(gift.level, gift);
            }
        }

        return new GiftConfig(gifts, guards);
    }

    public static LotteryInfoQueryResult queryLotteryInfo(BiliSession session, int room) throws IOException {
        if(session == null) {
            throw new IllegalArgumentException("this api requires login");
        }
        JSONObject obj = JSON.parseObject(HTTPHelper.doGetWithSession(
            String.format(LOTTERY_INFO, room, session),
            room,
            session
        ));
        if(obj.getIntValue("code") != 0) {
            throw new IllegalStateException("code is " + obj.getIntValue("code") + ", message: " + obj.getString("message"));
        }
        return obj.getObject("data", LotteryInfoQueryResult.class);
    }

    public static UserWithFace getUserWithFace(int uid) throws IOException {
        JSONObject obj = JSON.parseObject(HTTPHelper.doGet(String.format(METAL_ANCHOR_INFO, uid)));
        if(obj.getIntValue("code") != 0) {
            throw new IllegalStateException("code is " + obj.getIntValue("code") + ", message: " + obj.getString("message"));
        }
        JSONObject data = obj.getJSONObject("data");
        return new UserWithFace(data.getIntValue("ruid"), data.getString("runame"), data.getString("rface"));
    }

}
